package main

import (
	"errors"
	"fmt"
	"strings"
)

// 1、阶乘递归函数版
func factorial1(n int) (product int) {
	if n == 1 {
		product = 1
		return
	}
	product = n * factorial1(n-1)
	return
}

// 1、阶乘循环版
func factorial2(n int) (product int) {
	product = 1
	for i := 1; i <= n; i++ {
		product *= i
	}
	return
}

// 2、打印三角形
// 上三角
func ptriangle(n int) error {
	var ErrInputNum = errors.New("你输入非正整数，暂不支持")
	var space_w int  //定义空格宽度标识符
	var space string //定义存放每行前面所打印的空格
	if n <= 0 {
		return ErrInputNum
	} else if n < 10 {
		wth := n * 2 //wth是总打印宽度，下同
		for i := 1; i <= n; i++ {
			space_w = wth - i*2                  //计算出空格的宽度，下同，不同n得出的空格数量不同，所以下面n所处区间判断
			space = strings.Repeat(" ", space_w) //通过空格数量拼装空格存到space
			fmt.Printf("%s", space)              //每行打印前先打印空格
			for j := i; j > 0; j-- {             //按行打印实际数字
				fmt.Printf("%d ", j)
			}
			fmt.Println()
		}
	} else if n < 100 { //n是双位数时进行打印，同样进行判断
		wth := (n-9)*3 + 18
		for i := 1; i <= n; i++ {
			if i < 10 {
				space_w = wth - i*2
			} else {
				space_w = wth - 18 - (i-9)*3
			}
			space = strings.Repeat(" ", space_w)
			fmt.Printf("%s", space)
			for j := i; j > 0; j-- {
				fmt.Printf("%d ", j)
			}
			fmt.Println()
		}
	} else if n < 1000 { //实测n大于65时，debug窗口打印出来已经错位，是否输出，按需即可
		wth := (n-99)*4 + 270 + 18
		for i := 1; i <= n; i++ {
			if i < 10 {
				space_w = wth - i*2
			} else if i < 100 {
				space_w = wth - 18 - (i-9)*3

			} else {
				space_w = wth - 18 - 270
			}
			space = strings.Repeat(" ", space_w)
			fmt.Printf("%s", space)
			for j := i; j > 0; j-- {
				fmt.Printf("%d ", j)
			}
			fmt.Println()
		}
	} else {
		fmt.Println("n太大了,打印不完的")
	}
	return nil
}

/*
3、defer作用和应用：
1.作用：在函数内部注册需要延迟执行的函数，注册时，对defer后面的函数调用的实参固定，当return确定返回值之后，

	执行defer所注册的函数，按照注册倒序进行执行，即先注册的后执行
	panic之前注册的defer也会被执行，按照倒序执行
	defer完成后函数结束

2.应用：资源的打开和释放，比如，文件打开后，通过defer注册Close(),确保进程结束后能正确关闭打开的文件资源

	或是网络连接后断开，锁获得后的释放
	还可以在defer函数执行过程中通过操作具名返回值，影响return的返回值
*/
func main() {
	if err := ptriangle(30); err != nil {
		fmt.Println(err)
	}
	fmt.Println(factorial1(5))
	fmt.Println(factorial2(5))

}
